/** 
 * <p>Original Author:  jessefreeman</p>
 * <p>Class File: ReflectionEffect.as
 * 
 * <p>Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:</p>
 * 
 * <p>The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.</p>
 * 
 * <p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.</p>
 * 
 * <p>Licensed under The MIT License</p>
 * <p>Redistributions of files must retain the above copyright notice.</p>
 *
 * <p>Revisions<br/> 
 * 	0.1  Initial version Dec 26, 2008</p>
 *
 */

package camo.views.effects {
	import camo.views.display.CamoDisplay;
	
	import flash.display.*;
	import flash.events.EventDispatcher;
	import flash.events.TimerEvent;
	import flash.geom.*;
	import flash.utils.Timer;
	
	public class ReflectionEffect extends AbstractEffect{
		
		private var reflection_alpha:Number = .47;
		private var reflection_height:Number = 10;
		
		public function ReflectionEffect():void{
			super();
		}
		
		override protected function init():void{
			super.init();
		}
		
		/**
		 * Returns a reflection inside of a sprite of the image passed into it.
		 * @param: original:DisplayObject
		 **/
		private function reflection(original:DisplayObject):Sprite{
			var container:Sprite = createReflection(original);
			return container;
		}
		
		/**
		 * Returns original image along with reflection inside of a new Sprite
		 * @param: original:DisplayObject 
		 **/
		private function simpleReflection(original:DisplayObject):Sprite{
			var container:Sprite = new Sprite();
			
			// Create copy of orginal
			var image:Sprite = _imgUtil.copyImage(original);
				image.name = "image";
			
			// Create reflection
			var reflection:Sprite = reflection(original);
				reflection.y = image.height-1;
				trace(reflection.getChildByName("reflection_mask"));
			// Add image and reflection into container	
			container.addChild(image);
			container.addChild(reflection);
						
			return container;
		}
		
		/**
		 * This returns an image and reflection organized for animation. The image is placed a mask, and regrouped
		 * into a image_group sprite. Also the image's y is realign to make the image above the 0,0 registration mark
		 * and the reflection below the 0,0 mark.
		 **/
		/* private function advanced_reflection(original:DisplayObject):Sprite{
			var container:Sprite = simpleReflection(original);
			// Set up Image Group
			var image_group:Sprite = new Sprite();
				image_group.name = "image_group";
			// Select Image
			var image = container.getChildByName("image");
			var reflection_group = container.getChildByName("reflection_group");
			// Create Mask
			var mask:Sprite = create_mask(image.width+50,image.height+100);
			mask.x = -(mask.width/2 - image.width/2);
			mask.y = -(mask.height - image.height);
			mask.alpha = .5;
			
			// Add image and mask into group
			image_group.addChild(image);
			image_group.addChild(mask);
			
			// change registration point
			image_group.y = -(image.height);
			reflection_group.y = 0;
			// set mask
			image.mask = mask;
			
			// add image group back into container
			container.addChild(image_group);
			
			return container;
		} */
		
		/**
		 * 
		 */	
		internal function createReflection(original:DisplayObject):Sprite{
			
			var reflection:Sprite = new Sprite();
				reflection.name = "reflection_group";
				reflection.alpha = reflection_alpha;
				
			
			var image:Sprite = _imgUtil.copyImage(original, true);

			var reflect_mask:Sprite = _imgUtil.createGradientMask(original.width,original.height,reflection_height);
			
			reflection.addChild(image);
			
			
			reflection.addChild(reflect_mask);
			
			image.cacheAsBitmap = true;
			reflect_mask.cacheAsBitmap = true;
			image.mask = reflect_mask;
			
			return reflection;
			
		}
		
		/**
		 * Creates a bitmap copy of any DisplayObject passed in. It can also flip the image vertically for
		 * use with making a reflection.
		 * @param: original:DisplayObject
		 * @param flip: Boolean that defaults to false, use true to have it vertically flip the copy.
		 * @return container sprite with copy of original image inside.
		 **/
		 
		/* internal static function copy_image(original:DisplayObject,flip:Boolean = false):Sprite{
			
			// Create Container
			var container:Sprite = new Sprite();
				container.name = "copy";
			
			// Create BitmapData
			var data:BitmapData = new BitmapData(original.width, original.height, true, 0xFFFFFF);
			data.draw(original);
			
			// Create Bitmap
			var bmp:Bitmap = new Bitmap(data.clone());
			
			if(flip){
				bmp.scaleY = -1;
				bmp.y = bmp.height;
			}
			// Add bitmap to container			
			container.addChild(bmp);
			
			// Return container
			return container;
			
		} */
		
		/**
		 * 
		 */
		/* internal static function create_gradient_mask(width:Number,height:Number):Sprite{
			
			// Create container sprite for gradient
			var container:Sprite = new Sprite();
				container.name = "reflection_mask";
			
			// Draw Gradient			
			var rect:Shape = new Shape();
			var fillType:String = GradientType.LINEAR;
			var colors:Array = [0xFF0000, 0x000000];
			var alphas:Array = [100, 0];
			var ratios:Array = [0x00, 0xFF];
			var matr:Matrix = new Matrix();
			  	matr.createGradientBox(width, height/reflection_height, Math.PI / 2, 0, 20);
			var spreadMethod:String = SpreadMethod.PAD;
			
			rect.graphics.beginGradientFill(fillType, colors, alphas, ratios, matr, spreadMethod);  
			
			rect.graphics.drawRect(0,0,width,height);
			
			// Add Gradient to container
			container.addChild(rect);
			
			// Return Container
			return container;
		} */
		
		/**
		 * 
		 */
		internal static function create_mask(width:Number, height:Number, color:Number = 0xFF0000):Sprite{
			
			// Draw mask shape
			var mask:Sprite = new Sprite();
				mask.graphics.beginFill(0xFF0000);
				mask.graphics.drawRect(0, 0, width, height);
			
			// Return Mask
			return mask;		
		} 
		
		protected var _reflectionContainer:Sprite;
		protected var _reflectionMask:Sprite;
		
		override public function register(target:CamoDisplay):void{
			_reflectionContainer = new Sprite();
			target.addChild(_reflectionContainer);
			_reflectionMask = _imgUtil.createGradientMask(target.width,20,.4);
			_reflectionContainer.cacheAsBitmap = true;
			_reflectionMask.cacheAsBitmap = true;
			target.addChild(_reflectionMask);
			_reflectionContainer.mask = _reflectionMask;
			_reflectionContainer.alpha = .4;
			
			super.register(target);
			
		}
		
		protected var _timer:Timer;
		override protected function registerEventListeners(target:EventDispatcher):void{
			_timer = new Timer(10,0);
			_timer.addEventListener(TimerEvent.TIMER,onUpdate);
			_timer.start();
		}
		
		/* public function getReflectionBitmapData(source: DisplayObject, percent:Number = .5, fromBottom:Boolean = false):BitmapData{
			
		} */
		 
		override public function refresh():void{
			
			var data : BitmapData = new BitmapData(_effectTarget.display.width, _effectTarget.display.height, true, 0xFFFFFF);
				data.draw(_effectTarget);
			
			var scale : Number = _effectTarget.height * .2;
			
			var m : Matrix = new Matrix();
				m.d=-1;
			
			_reflectionContainer.graphics.clear();
			_reflectionContainer.graphics.beginBitmapFill(data, m);
			_reflectionContainer.graphics.drawRect(0,0,_effectTarget.width,scale);
			
			_reflectionContainer.y = _reflectionMask.y = _effectTarget.display.height - 6;// - _effectTarget.margin["bottom"] - _effectTarget.padding["bottom"];
			
		}
	}
}


